/*
 * Copyright 2003-2005 (c) Live Media Pty Ltd. <argot@einet.com.au> 
 *
 * This software is licensed under the Argot Public License 
 * which may be found in the file LICENSE distributed 
 * with this software.
 *
 * More information about this license can be found at
 * http://www.einet.com.au/License
 * 
 * The Developer of this software is Live Media Pty Ltd,
 * PO Box 4591, Melbourne 3001, Australia.  The license is subject 
 * to the law of Victoria, Australia, and subject to exclusive 
 * jurisdiction of the Victorian courts.
 */

#include "../Types.h"

#include "Dictionary.h"
#include "DictionaryTypes.h"

#include "../common/Error.h"
#include "../common/BigEndianUnsignedShort.h"
#include "../common/BigEndianUnsignedByte.h"

#include "../meta/MetaExpression.h"
#include "../meta/MetaAbstract.h"
#include "../meta/MetaArray.h"
#include "../meta/MetaBasic.h"
#include "../meta/MetaDefinition.h"
#include "../meta/MetaMap.h"
#include "../meta/MetaMarshaller.h"
#include "../meta/MetaName.h"
#include "../meta/MetaReference.h"
#include "../meta/MetaSequence.h"
#include "../meta/MetaEnvelop.h"

#include "TypeMapMarshaller.h"

int dictionary_types_init(type_library * library)
{
	int metaEnvelopId;
	int rc;
	
	if ( type_library_get_state( library, &meta_envelop_name ) != TYPE_COMPLETE )
	{
		
	    meta_sequence * envelopSeq = (meta_sequence *) type_malloc( sizeof( meta_sequence ) );
	    meta_reference * envelopRefSize = (meta_reference *) type_malloc( sizeof( meta_reference ) );
	    meta_reference * envelopRefType = (meta_reference *) type_malloc( sizeof( meta_reference ) );
	    meta_expression ** envelopSeqObjs = (meta_expression **) type_malloc( sizeof( meta_expression *) * 2 );
	    
	    meta_reference_init( envelopRefSize, type_library_get_id( library, &meta_expression_name ), "size" );
	    meta_reference_init( envelopRefType, type_library_get_id( library, &meta_expression_name ), "type" );
	    envelopSeqObjs[0] = (meta_expression *) envelopRefSize;
	    envelopSeqObjs[1] = (meta_expression *) envelopRefType;
	    meta_sequence_init( envelopSeq, envelopSeqObjs, 2 );
	    		

		metaEnvelopId = type_library_register_bind( library, &meta_envelop_name, (type_element *) envelopSeq, &meta_read, NULL, &meta_envelop_write, NULL );
		if ( metaEnvelopId <= NOTYPE )
			return metaEnvelopId;

	}
	else
	{
		metaEnvelopId = type_library_get_id( library, &meta_envelop_name );	
	}
		

	if ( type_library_get_state( library, &meta_definition_envelop_name ) != TYPE_COMPLETE )
	{
		int metaDefinitionId = type_library_get_id( library, &meta_definition_name );
		
		meta_map * expRef = (meta_map *) type_malloc( sizeof( meta_map ));
		meta_map_init( expRef, metaDefinitionId, metaEnvelopId );
		rc = type_library_register_bind( library, &meta_definition_envelop_name, (type_element *) expRef, &meta_read, NULL, &meta_write, NULL );
		if ( rc <= NOTYPE )
			return rc;
	}
		
	if ( type_library_get_state( library, &dictionary_definition_name ) != TYPE_COMPLETE )
	{
		
	    meta_envelop * dictDefEnv = (meta_envelop *) type_malloc( sizeof( meta_envelop ) );
	    meta_reference * dictDefRefSize = (meta_reference *) type_malloc( sizeof( meta_reference ) );
	    meta_reference * dictDefRefDef = (meta_reference *) type_malloc( sizeof( meta_reference ) );
	    
	    meta_reference_init( dictDefRefSize, type_library_get_id( library, &uint16_name ), "size" );
	    meta_reference_init( dictDefRefDef, type_library_get_id( library, &meta_definition_name ), "definition" );
	    meta_envelop_init( dictDefEnv, (meta_expression *) dictDefRefSize, (meta_expression *) dictDefRefDef );
	    		

		metaEnvelopId = type_library_register_bind( library, &dictionary_definition_name, (type_element *) dictDefEnv, &meta_read, NULL, &meta_write, NULL );
		if ( metaEnvelopId <= NOTYPE )
			return metaEnvelopId;

	}
		
	if ( type_library_get_state( library, &dictionary_entry_name ) != TYPE_COMPLETE )
	{
		
	    meta_sequence * entrySeq = (meta_sequence *) type_malloc( sizeof( meta_sequence ) );
	    meta_reference * entryRefId = (meta_reference *) type_malloc( sizeof( meta_reference ) );
	    meta_reference * entryRefName = (meta_reference *) type_malloc( sizeof( meta_reference ) );
	    meta_reference * entryRefDef = (meta_reference *) type_malloc( sizeof( meta_reference ) );
	    meta_expression ** entrySeqObjs = (meta_expression **) type_malloc( sizeof( meta_expression *) * 3 );
	    
	    meta_reference_init( entryRefId, type_library_get_id( library, &uint16_name ), "id" );
	    meta_reference_init( entryRefName, type_library_get_id( library, &meta_name_name ), "name" );
	    meta_reference_init( entryRefDef, type_library_get_id( library, &dictionary_definition_name ), "definition" );
	    entrySeqObjs[0] = (meta_expression *) entryRefId;
	    entrySeqObjs[1] = (meta_expression *) entryRefName;
	    entrySeqObjs[2] = (meta_expression *) entryRefDef;
	    meta_sequence_init( entrySeq, entrySeqObjs, 3 );
	    		

		metaEnvelopId = type_library_register_bind( library, &dictionary_entry_name, (type_element *) entrySeq, &meta_read, NULL, &meta_write, NULL );
		if ( metaEnvelopId <= NOTYPE )
			return metaEnvelopId;

	}


	if ( type_library_get_state( library, &dictionary_map_name ) != TYPE_COMPLETE )
	{
		
	    meta_sequence * mapSeq = (meta_sequence *) type_malloc( sizeof( meta_sequence ) );
	    meta_reference * mapRefSize = (meta_reference *) type_malloc( sizeof( meta_reference ) );
	    meta_reference * mapRefWord = (meta_reference *) type_malloc( sizeof( meta_reference ) );
	    meta_expression ** mapSeqObjs = (meta_expression **) type_malloc( sizeof( meta_expression *) * 2 );
	    meta_array * mapAry = (meta_array *) type_malloc( sizeof( meta_array ) );
	    
	    meta_reference_init( mapRefSize, type_library_get_id( library, &uint16_name ), "size" );
	    meta_reference_init( mapRefWord, type_library_get_id( library, &dictionary_entry_name ), "word" );
	    meta_array_init( mapAry, (meta_expression *) mapRefSize, (meta_expression *) mapRefWord );	  
	    mapSeqObjs[0] = (meta_expression *) mapAry;
	    meta_sequence_init( mapSeq, mapSeqObjs, 1 );
	    		

		metaEnvelopId = type_library_register_bind( library, &dictionary_map_name, (type_element *) mapSeq, &error_read, NULL, &type_map_write, NULL );	
		if ( metaEnvelopId <= NOTYPE )
			return metaEnvelopId;

	}
				

	if ( type_library_get_state( library, &dictionary_words_name ) != TYPE_COMPLETE )
	{
		
	    meta_envelop * wordsDefEnv = (meta_envelop *) type_malloc( sizeof( meta_envelop ) );
	    meta_reference * wordsDefRefSize = (meta_reference *) type_malloc( sizeof( meta_reference ) );
	    meta_reference * wordsDefRefMap = (meta_reference *) type_malloc( sizeof( meta_reference ) );
	    
	    meta_reference_init( wordsDefRefSize, type_library_get_id( library, &uint16_name ), "size" );
	    meta_reference_init( wordsDefRefMap, type_library_get_id( library, &dictionary_map_name ), "words" );
	    meta_envelop_init( wordsDefEnv,(meta_expression*) wordsDefRefSize, (meta_expression*) wordsDefRefMap );
	    		

		metaEnvelopId = type_library_register_bind( library, &dictionary_words_name, (type_element *) wordsDefEnv, &meta_read, NULL, &meta_write, NULL );
		if ( metaEnvelopId <= NOTYPE )
			return metaEnvelopId;

	}

	return TYPE_OK;
}
